<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /*
         实现异步的方案 ：
             方案一： 回调函数
               就一个方法作为另一个函数的参数
             方案二：发布订阅者模式（监听者模式）
             方案三： Promise

        */

      // 对于方案二的简单实现

      //   class Emit {
      //     constructor() {
      //       this._funcpoll = [];
      //     }

      //     // 监听方法,将传入的回调函数都保存起来
      //     on(type, fn) {
      //       this._funcpoll[type]
      //         ? this._funcpoll.push(fn)
      //         : (this._funcpoll[type] = fn);
      //     }

      //     // 执行监听方法
      //     trigger(type, ...rest) {
      //       if (!this._funcpoll[type]) return;
      //       this._funcpoll.forEach((callback) => callback(...rest));
      //     }
      //   }

      //   const emitter = new Emit();

      //   emitter.on("done", (...rest) => {
      //     console.log(...rest);
      //   });

      //   emitter.on("done", (...rest) => {
      //     console.log(...rest);
      //   });

      //   function fn1() {
      //     console.log("我是主程序");
      //     setTimeout(() => {
      //       emitter.trigger("done", 1, 2, 3);
      //       emitter.trigger("done", 4, 5, 6);
      //     }, 1000);
      //   }

      //   fn1();

      //  vue 中的 emit 方法和这个实现很相似
      //  缺点： 整个程序变成了事件驱动，流程上来说或多或少都会有点影响，每次使用还得注册事件监听再进行触发挺麻烦的，代码也不太优雅，并不是事件驱动不好，毕竟需求只是 解决异步问题 而已，何况有更优解
      //  优点： 发布订阅模式实现的事件监听，我们可以绑定多个事件，每个事件也可以指定多个回调函数，还是比较符合模块化思想的，我们自写监听器时可以做很多优化从而更好的监控程序运行

      // ==========方案三：同步的方式写异步的代码=========
      //   let p = new Promise((resolve, reject) => {
      //     resolve(1);
      //   });

      //   p.then((data) => 2)
      //     .then(
      //       (data) => {
      //         throw "this is err";
      //       },
      //       (err) => {
      //         console.log("err1:" + err);
      //       }
      //     )
      //     .then(
      //       (data) => {
      //         console.log(data);
      //       },
      //       (err) => {
      //         console.log("err2:" + err); // err2:this is err
      //       }
      //     );
      // 规范中定义当前then方法出现异常则调用失败态方法(reject)流转到下一个then的onRejected

      // ====================

      //   let p = new Promise((resolve, reject) => {
      //     resolve(1);
      //   });

      //   p.then((data) => 2)
      //     .then(
      //         data=>{
      //             return new Promise((resolve,reject)=>{ // 如果 then 方法中返回一个Promise 对象，那么就以这个对象为准，返回他的结果
      //                 resolve(1)
      //             })
      //         }
      //     )
      //     .then()
      //     .then((data) => {
      //       console.log(data); // 1
      //       throw 'this is a error'
      //     }).catch(res=>{
      //         console.log(res);
      //         return res  // 如果被成功捕获到他会返回一个成功的 Promise
      //     }).then(res=>{
      //         console.log('this resolve'); // this resolve
      //     },err=>{
      //         console.log("this reject");
      //     }).catch(res=>{
      //         console.log(res);
      //     })

      // 如果then方法没有传入任何回调，则继续向下传递(即所谓的值穿透),使用 catch 如果被成功捕获到他会返回一个成功的 Promise

      // ======Promise.all(迭代对象中状态全部改变才会执行),Promise.race()方法正好相反，只要迭代对象中有一个状态改变了，它的状态就跟着改变，并将那个改变状态实例的返回值传递给回调函数=======

      //   应用场景在我们有一个接口，需要其他两个或多个接口返回的数据作为参数时会多一些
      // let p1 = Promise.resolve(1);
      // //   let p2 = Promise.reject(2);
      // let p2 = Promise.resolve(2);
      // let p3 = Promise.resolve(3);

      // //   let p = Promise.all([p1, p2, p3]);
      // let p = Promise.race([p1, p2, p3]); // 不会等待，直接就会执行第一个成功的Promise
      // p.then((data) => {
      //   console.log(data);
      // }).catch((err) => {
      //   console.log("err:" + err); // 1
      // });

      // //   ============

      // const abc = Symbol("foo");
      // const o = {
      //   [abc]: 123,
      // };
      // console.log(o[abc]);

      // // ============
      // const pro = new Promise((resolve, reject) => {
      //   resolve(2)
      // })

      // console.dir(Promise);
      // // console.log("promise----", pro.then());

      // // 测试函数中对象
      // function arg (){
      //   console.log(arguments);
      // }
      // arg()

      const p = new Promise((resolve, reject) => {
        // const newp = new Promise((resolve, reject) => {
        //   resolve('success')
        // })
        reject('newp');
      }).then(res => {
        console.log('🚀 ~ This is a result of console.log ~ ✨: res2', res);
      }).catch(res => {
        console.log('🚀 ~ This is a result of console.log ~ ✨catch: ', res);
      })

      // console.log('🚀 ~ This is a result of console.log ~ ✨: ', p);
      console.dir(p)

    </script>
  </body>
</html>
